package com.sinaapp.gavinzhang.GSpider.webaddress;

import com.caucho.hessian.client.HessianRuntimeException;
import com.caucho.hessian.server.HessianServlet;
import com.sinaapp.gavinzhang.GSpider.common.IpUtil;
import com.sinaapp.gavinzhang.GSpider.common.RegisterUtil;
import com.sinaapp.gavinzhang.GSpider.common.ServletUtil;
import com.sinaapp.gavinzhang.GSpider.management.HeartBeat;
import com.sinaapp.gavinzhang.GSpider.management.Register;
import com.sinaapp.gavinzhang.GSpider.management.RegistrationCenter;
import com.sinaapp.gavinzhang.GSpider.management.Stub;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author gavin
 * @version 1.0
 * @date 2016/3/19
 * @description Galileo
 * 网址管理器
 */
public class URLManagement extends HessianServlet implements URLDispatcher{
    private static final Logger logger = LoggerFactory.getLogger(URLManagement.class);

    public final static int DEFAULT_PORT = 20001;

    private static String centerIp;
    private static int centerPort;
    public final static Stub urlStub = Stub.newStub();

    private WebUrlCollection pendingWebUrlQue;
    private WebUrlCollection visitedWebUrlSet;


    public URLManagement() {
        this(PendingWebUrlList.newPendingWebUrlList(), VisitedWebUrlList.newVisitedWebUrlList());
    }

    public URLManagement(WebUrlCollection pendingWebUrlQue, WebUrlCollection visitedWebUrlSet) {
        this.pendingWebUrlQue = pendingWebUrlQue;
        this.visitedWebUrlSet = visitedWebUrlSet;
    }

    /**
     * @descprition 获取网址，有可能是阻塞的，有可能是非阻塞的。
     * 非阻塞有可能返回null
     * 返回结果前先判断是否被处理过了，处理过了则返回null
     * @return
     */
    @Override
    public WebAddress get() {
        WebAddress webAddress = this.pendingWebUrlQue.get();
        if (webAddress != null) {
            if (!this.visitedWebUrlSet.exist(webAddress)) {
                this.visitedWebUrlSet.add(webAddress);
                logger.info("append: " + webAddress);
                return webAddress;
            }

        }
        return null;
    }

    /**
     * @descriptio 如果已抓取列表中已经存在该网址，则不放入待抓取列表中
     * @param webAddress
     */
    @Override
    public void add(WebAddress webAddress) {
        if (!this.visitedWebUrlSet.exist(webAddress)) {
            logger.info("add: " + webAddress);
            this.pendingWebUrlQue.add(webAddress);
        } else {
            logger.info("exists: " + webAddress);
        }
    }

    @Override
    public int visitedSize() {
        return visitedWebUrlSet.size();
    }

    @Override
    public int pendingSize() {
        return pendingWebUrlQue.size();
    }

    @Override
    public int echo() {
        return HEARTECHO;
    }

    @Override
    public void shutdown() {
        System.exit(HEARTECHO);
    }

    public static void setUp() throws Exception {
        logger.warn("注册中心IP为:(默认)" + IpUtil.getRealIp());
        setUp(IpUtil.getRealIp());
    }

    public static void setUp(String ip) throws Exception {
        logger.warn("注册中心端口号为:(默认)" + RegistrationCenter.DEFAULT_PORT);
        setUp(ip, RegistrationCenter.DEFAULT_PORT);
    }

    public static void setUp(int localPort)throws Exception{
        logger.warn("注册中心IP为:(默认)" + IpUtil.getRealIp());
        logger.warn("注册中心端口号为:(默认)" + RegistrationCenter.DEFAULT_PORT);
        setUp(IpUtil.getRealIp(),RegistrationCenter.DEFAULT_PORT,localPort);
    }


    public static void setUp(String ip, int port) throws Exception {
        logger.warn("网址管理器端口号为:(默认)" + URLManagement.DEFAULT_PORT);
        setUp(ip, port, URLManagement.DEFAULT_PORT);
    }

    public static void setUp(String ip, int port, int localPort) throws Exception {
        logger.info("注册中心IP为:"+ip);
        logger.info("注册中心端口号为:"+port);
        logger.info("网址管理器端口号为:"+localPort);
        centerIp = ip;
        centerPort = port;

        //得到管理中心
        logger.info("获取注册中心服务");
        Register center = RegisterUtil.getRegister(ip, port, RegistrationCenter.REGISTRATIONCENTER);

        //注册服务
        logger.info("注册网址管理器");
        String name = "http://" + IpUtil.getRealIp() + ":" + localPort + "/" + RegistrationCenter.URLDISPATCHER + "." + urlStub.getToken();
        urlStub.setName(name);
        logger.info("注册中..."+urlStub);
        try {
            if (center.Registrate(urlStub).equals(Stub.getNoneStub())) {
                logger.error("注册失败!");
                System.exit(-1);
            }
        }catch (HessianRuntimeException e){
            logger.error("注册中心连接超时!"+centerIp+":"+centerPort);
            System.exit(-1);
        }

        logger.info("注册成功!");

        //启动jetty服务
        Server server = new Server(localPort);
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        server.setHandler(context);
        logger.info("GServer 启动中...");
        ServletUtil.addServlet(context, URLManagement.class, "/" + RegistrationCenter.URLDISPATCHER + "." + urlStub.getToken());
        logger.info("GServer 添加RPC网址管理服务成功!");
        server.start();
        logger.info("GServer 地址: " + server.getURI().toString());
        logger.info("GServer 启动成功!" + server.getState());
        //server.join();
    }


    public static void main(String[] args) {
        try {
            URLManagement.setUp("127.0.0.1");
            //URLManagement.setUp();
            System.out.println("ok");
        } catch (Exception e) {
            if (e.getMessage().contains("java.net.ConnectException") || e.getMessage().contains("Timeout")) {
                logger.error("无法连接注册中心",e);
            }else {
                e.printStackTrace();
            }
        }

    }
}
